using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Universe.Farm.Service.Mesages;

namespace Universe.Farm.Service
{
    public class Farm : IFarmService
    {
        private readonly ConfigurationContainer _Config;
        private FarmState _State;

        
        
        public Farm(ConfigurationContainer config)
        {
            _Config = config;

            
            HealthCollection hic = new HealthCollection();
            _Config.Register<IHealthCollection>(delegate { return hic; });

            List<DeliveryAgent> dal = new List<DeliveryAgent>();
            _Config.Register<List<DeliveryAgent>>(delegate { return dal; });

            DefaultLookupRequestSender sender = new DefaultLookupRequestSender(_Config);
            _Config.Register<ILookupRequestSender>(delegate { return sender; });

            IStateStorage ss = _Config.Resolve<IStateStorage>();
            if (ss == null)
            {
                ss = new RegistryStateStorage();
                _Config.Register<IStateStorage>(delegate { return ss; });
            }

            CommunicationParameters cp = _Config.ResolveRequired<CommunicationParameters>();

            IBufferProtocol bp = _Config.Resolve<IBufferProtocol>();
            if (bp == null)
            {
                bp = new BufferProtocol(cp.IntegrityAlgorithm);
                _Config.Register<IBufferProtocol>(delegate { return bp; });
            }

        }

        public IList<HealthInfo> GetServices(ServicesScope scope)
        {
            IHealthCollection state = _Config.ResolveRequired<IHealthCollection>();
            return state.GetServices(scope);
        }

        public void LookupServices(ServicesScope scope)
        {
            ILookupRequestSender sender = _Config.ResolveRequired<ILookupRequestSender>();
            sender.SendLookupMessage(scope);
        }

        private void SendBye()
        {
            IStateStorage stateStorage = _State.Config.ResolveRequired<IStateStorage>();
            TimeStampIO io = new TimeStampIO(stateStorage, "Generic");
            TimeStamp ts = io.GetNext();

            ByeMessage byeMessage = new ByeMessage(new MessageHeader(CommunicationParameters.ComputerID, ts));
            byeMessage.Computer = Environment.MachineName;
            foreach (DeliveryAgent agent in _State.DeliveryStations)
                agent.Deliver(byeMessage);
        }

        class DefaultLookupRequestSender : ILookupRequestSender
        {
            private ConfigurationContainer _config = null;

            public DefaultLookupRequestSender(ConfigurationContainer config)
            {
                _config = config;
            }

            public void SendLookupMessage(ServicesScope scope)
            {
                IStateStorage stateStorage = _config.ResolveRequired<IStateStorage>(); 
                TimeStampIO io = new TimeStampIO(stateStorage, "Generic");
                TimeStamp ts = io.GetNext();

                LookupRequestMessage lookupMessage = new LookupRequestMessage(ts, CommunicationParameters.ComputerID, scope);
                List<DeliveryAgent> deliveryStations = _config.ResolveRequired<List<DeliveryAgent>>();
                foreach (DeliveryAgent agent in deliveryStations)
                    agent.Deliver(lookupMessage);
            }

        }

        public void Start()
        {
            FarmState state = new FarmState(_Config);

            state.NetListeners.Add(new NetListenerAgent(state));
            state.DeliveryStations.Add(new DeliveryAgent(state));

            foreach (ServiceListenerConfiguration listenetConfig in state.ServiceListenerConfigList)
            {
                ServiceListenerAgent sl = new ServiceListenerAgent(
                    state, 
                    listenetConfig.ServiceListener, 
                    listenetConfig);

                state.ServiceListeners.Add(sl);
            }
            _State = state;

            foreach (NetListenerAgent agent in state.NetListeners)
            {
                agent.Start();
            }

            foreach (DeliveryAgent agent in state.DeliveryStations)
            {
            }

            foreach (ServiceListenerAgent agent in state.ServiceListeners)
            {
                agent.Start();
            }
        }

        public bool Stop()
        {
            this.SendBye();

            FarmState state = _State;

            foreach (ServiceListenerAgent listener in state.ServiceListeners)
            {
                listener.Stop();
            }

            foreach (NetListenerAgent listener in state.NetListeners)
            {
                listener.Stop();
            }

            foreach (DeliveryAgent station in state.DeliveryStations)
            {
                station.Close();
            }

            _State = null;
            return true;
        }


        public IHealthCollection LocalInfo
        {
            get { return _State.HealthState; }
        }


    }
}
